<?php
/**
 * ACL FSExt backend
 *
 * This backend understands Principals.
 *
 * Copyright © 2010 Jack Cleaver
 * 
 * This plugin provides functionality added by CalDAV (RFC 4791)
 * It implements new reports, and the MKCALENDAR method.
 *
 * This file is part of Slash.
 *
 * Slash is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Slash is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Slash.  If not, see <http://www.gnu.org/licenses/>.
 */
class Slash_ACL_FSExt_Directory 
extends Sabre_DAV_FSExt_Directory
{

	public $propertyMap = array("{DAV:}displayname");

	public function __construct($path)
	{
		//Slash_Debug::debug("Constructing Slash_ACL_FSExt_Directory: $path");
		parent::__construct($path);
	}

	
	public function getChild($name)
	{

		$path = $this->path . '/' . $name;

		if (!file_exists($path))
		{
			throw new Sabre_DAV_Exception_FileNotFound("File '$path' could not be located");
		}
		if ($name=='.' || $name=='..')
		{
			throw new Sabre_DAV_Exception_Forbidden('Permission denied to . and ..');
		}

		if (is_dir($path))
		{
			//Slash_Debug::debug("ACL_FSExt_Directory getChild: path=$path");
			if ($this->isPrincipalRoot())
			{
				//Slash_Debug::debug("ACL_FSExt_Directory getChild: returning a Principal");
				return new Slash_ACL_FSExt_Principal($path);
			} else {
				//Slash_Debug::debug("CalDAV_FSExt_Directory getChild: returning a Directory");
				return new Slash_ACL_FSExt_Directory($path);
			}
		} else {
			//Slash_Debug::debug("CalDAV_FSExt_Directory getChild: returning a File");
			return new Sabre_DAV_FSExt_File($path);
		}
	}

	function isPrincipalRoot()
	{
		$server = Slash_CalDAV_Server::getInstance();
		$principalRoot = Slash_CalDAV_Server::getPrincipalRoot();
		$baseUri = $server->tree->getNodeForPath("/")->path;
		//Slash_Debug::debug("ACL_FSExt_Directory isPrincipalRoot: this=" . $this->path . ", root=$baseUri/$principalRoot");
		return ($this->path == "$baseUri/$principalRoot");
	}
	
	public function createDirectory($name)
	{
		Slash_Debug::debug("ACL_FSExt_Directory createDirectory:  path=$this->path, name=$name");
		if ($this->isPrincipalRoot())
		{
			$this->createPrincipal($name);
		} else {
			parent::createDirectory($name);
		}
	}


	public function createPrincipal($principalName)
	{
		//throw new Sabre_DAV_Exception ("Create a calendar");
		// Default value
		Slash_Debug::debug("ACL_FSExt_Directory createPrincipal: $principalName");		
		try
		{
			$this->getChild($principalName);

			// If we got here.. it means there's already a node on that url, and we need to throw a 405
			throw new Sabre_DAV_Exception_MethodNotAllowed('CalDAV Directory: The resource you tried to create already exists');

		}
		catch (Sabre_DAV_Exception_FileNotFound $e)
		{
		}
		//if (!$this->broadcastEvent('beforeBind',array($uri))) return;

		//throw new Sabre_DAV_Exception ("Create a directory $calendarName");
		parent::createDirectory($principalName);
		Slash_Debug::debug("in createPrincipal, created directory for $principalName");
		$rollBack = false;
		$exception = null;
		$errorResult = null;

		$properties["{DAV:}displayname"] = $principalName;
		$href = new Slash_ACL_Property_Href("/principals/admins");
		$owner = new  Slash_ACL_Property_Owner($href);
		$properties["{DAV:}owner"] = $owner;
		
		$acl = new Slash_ACL_Property_Acl("Principal ACL");
		
		$princ = new Slash_ACL_Property_SelfPrincipal(); 
		$acl->grant($princ, array("all"), true);
		Slash_Debug::debug("CalDAV_FSExt_Directory createPrincipal, granted all to self principal");
		
		$princ = new Slash_ACL_Property_PropertyPrincipal("DAV:", "owner");
		$acl->grant($princ, array("all"), true);
		Slash_Debug::debug("CalDAV_FSExt_Directory createPrincipal, granted all to owner principal: " . $princ->toString());
		
		$properties["{DAV:}acl"] = $acl;
		
		$properties["{DAV:}resourcetype"] = new Sabre_DAV_Property_ResourceType(array('{DAV:}principal','{DAV:}collection'));

		$properties["{http://jackpot.uk.net/slash}password"] = "password";
		try
		{
			$principal = $this->getChild($principalName);
			$errorResult = $principal->updatePrincipal($properties);
			//Slash_Debug::debugDump("in createPrincipal, errorResult: ", $errorResult);
			if (!isset($errorResult[200]))
			{
				$rollBack = true;
			}
		}
		catch (Sabre_DAV_Exception $e)
		{
			$msg = $e->getMessage();
			Slash_Debug::debug("CalDAV_FSExt_Directory createPrincipal, caught exception $msg");
			$rollBack - true;
			$exception = $e;
		}
		if ($rollBack)
		{
			Slash_Debug::debug("in createPrincipal, rolling back");
			$node = $this->getChild($calendarName);
			//if (!$this->broadcastEvent('beforeUnbind',array($uri))) return;
			$node->delete();
			throw $exception;
		}
		Slash_Debug::debugDump("CalDAV_FSExt_Directory createPrincipal, ACL stored for principal: ". $principal->getName(), $acl);
		return $errorResult;
	}
}
